#pragma once
#ifndef _INSTANCE_H
#define _INSTANCE_H

#include "horse.h"
#include "utils.h"

class Instance
{
public:
	//2dim. vector of uns.ints..
	typedef std::vector<std::vector<size_t> > penalties_t;
	typedef std::vector<Horse> horses_t;

	const size_t n, //velikost sachovnice
		k, //pocet jezdcu
		q; //max. pocet tahu do reseni

	//Ctor.
	Instance(
		const size_t _n, //velikost desky
		const size_t _k, //pocet konu
		const size_t _q, //pocet nahodnych tahu
		const penalties_t& _pens, //vektor vektoru celych cisel
		const horses_t& _hors //vektor souradnic (konu)
		):
	n(_n),k(_k),q(_q)
	{
		checkNumParams();
		penalties = _pens;
		checkPensVector();
		horses = _hors;
		checkHorsVector();
	}

	
	//returns penalty for given coordinates
	//performs bounds checking
	size_t getPenalty(const size_t x, const size_t y) const
	{
		return penalties.at(y).at(x);
	}

	size_t getPenalty(const utils::coords_t c) const
	{
		return getPenalty(c.first, c.second);
	}


	// returns horses
	const horses_t& getHorses() const {
		return horses;
	}
	

	virtual ~Instance()
	{}

private:
	//vector of vectors of penalties
	penalties_t penalties;

	//vector of horses
	horses_t horses;


	//checks given params - board size, horses count, turns count
	//throws an exception if failed
	void checkNumParams()
	{
		if (n<5 || k<n || k>n*(n+1)/2 || q<n || q>n*n)
		{
			throw "numeric parameters of this instance are out of allowed range";
		}
	}


	//check penalties vector
	//throws an exception if failed
	void checkPensVector()
	{
		if (penalties.size() != n)
		{
			throw "invalid column size";
		}
		for(size_t i = 0; i < penalties.size(); i++)
		{
			if(penalties[i].size() != n)
			{
				throw "invalid row length";
			}
		}
	}

	//check horses vector
	//throws an exception if failed
	void checkHorsVector()
	{
		if (horses.size() != k)
		{
			throw "invalid horses count";
		}
	}
};

#endif //Instance.h
